package com.ruoyi.partybuilding.controller;

import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import com.alibaba.fastjson2.JSONObject;
import com.easy.query.api4j.select.Queryable;
import com.easy.query.api4j.util.EasyLambdaUtil;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.page.PageDomain;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.partybuilding.common.*;
import com.ruoyi.partybuilding.common.EQuery.IDeptEntity;
import com.ruoyi.partybuilding.domain.*;
import com.ruoyi.partybuilding.domain.vo.DeptOrgVo;
import com.ruoyi.partybuilding.domain.vo.ScoreYearStatVo;
import com.ruoyi.partybuilding.service.impl.OrgServiceImpl;
import com.ruoyi.partybuilding.service.impl.TeamRecordServiceImpl;
import com.ruoyi.partybuilding.service.impl.WorkScoreServiceImpl;
import io.swagger.annotations.*;
import lombok.var;
import org.apache.commons.collections4.keyvalue.DefaultKeyValue;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.util.function.*;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;


@Api(tags = "大屏数据")
@RestController
@RequestMapping("/partybuilding/DataStat")
public class DataStatController extends EQueryController<Org> {

    @Resource
    OrgServiceImpl orgService;
    @Resource
    WorkScoreServiceImpl scoreService;
    /*
    //个人
    @ApiOperation(value = "个人统计信息",notes = "t1人员数量,t2组织数量")
    @GetMapping(value = "myData")
    public R<Tuple2<Long,Integer>> myData(){
        var where=new DeptOrgVo();
        where.setDeptId(getDeptId());
        var deptStat = orgService.deptInfoStat(where);
        var re= deptStat.getData().stream().filter(p-> Objects.equals(p.getDeptId(), getDeptId())).findFirst();
        var memberCount=re.get().getStatMember();
        var orgCount=deptStat.getData().size();
        //
        var tuple= Tuples.of(memberCount,orgCount);
        return R.ok(tuple);
    }
*/
    //党员
    @Cacheable(cacheNames = "dataStat" ,keyGenerator = "classMethodKey")
    @ApiOperation(value = "党员统计信息",notes = "t1党员统计[[值,说明]],t2汉族人数，t3学历[[值,说明]]，t4男性人数(总数在党员统计中),t5男性年龄分布[[值,说明]],t6女性年龄分布[[值,说明]]")
    @ApiResponse(code = 200, message = "成功示例", examples = @Example({@ExampleProperty(ConstData.DataStatMemberExample)}))
    @GetMapping(value = "memberStat")
    public R<Tuple6<List<Comparable[]>, Long, List<Comparable[]>, Long, List<Comparable[]>,List<Comparable[]>>> memberStat(Long deptId) {
        var baseQuery = queryHelper.queryable(UserMemberDeptV.class)
                .where(p -> p.eq(UserMemberDeptV::getDelFlag, 0).isNotNull(UserMemberDeptV::getId))
                .where(deptId != null, p ->
                    p.and(x-> x.eq(UserMemberDeptV::getDeptId, deptId).or().sqlNativeSegment("FIND_IN_SET({0},{1})", z -> z.value(deptId).expression(UserMemberDeptV::getDeptAncestors)))
                );

        //党员信息
        var memberCount = baseQuery.cloneQueryable().count();
        var mType0Query = baseQuery.cloneQueryable().where(p -> p.eq(UserMemberDeptV::getMemberType, 0));
        var mType0Count = mType0Query.cloneQueryable().count();
        var mType0ManCount = mType0Query.cloneQueryable().where(p -> p.eq(UserMemberDeptV::getSex, 0)).count();
        var mtype0Young = mType0Query.cloneQueryable().where(p -> p.ge(UserMemberDeptV::getBirth, DateUtils.addYears(new Date(), -35))).count();
        //
        var mtype1Query = baseQuery.cloneQueryable().where(p -> p.eq(UserMemberDeptV::getMemberType, 1));
        var mtype1Count = mtype1Query.cloneQueryable().count();
        var mtype1ManCount = mtype1Query.cloneQueryable().where(p -> p.eq(UserMemberDeptV::getSex, 0)).count();

        var memberList=new ArrayList<>();
        memberList.add(new Object[]{memberCount,"党员总数：预备及正式"});
        memberList.add(new Object[]{mType0Count,"预备党员数"});
        memberList.add(new Object[]{mType0ManCount,"预备党员-男数量"});
        memberList.add(new Object[]{mtype0Young,"35岁前预备党员数"});
        memberList.add(new Object[]{mtype1Count,"正式党员数"});
        memberList.add(new Object[]{mtype1ManCount,"正式党员-男数量"});
        //民族
        var hanCount = baseQuery.cloneQueryable().where(p -> p.eq(UserMemberDeptV::getNation, "汉族")).count();
        //学历
        var edus = baseQuery.cloneQueryable()
                .groupBy(p -> p.column(UserMemberDeptV::getEducation))
                .select(DefaultKeyValue.class, p -> {
                    p.columnAs(UserMemberDeptV::getEducation, "key");
                    p.getColumnAsSelector().columnCountAs(EasyLambdaUtil.getPropertyName(UserMemberDeptV::getEducation), "value");
                }).toList().stream().map(p->new Object[]{p.getValue(),p.getKey()}).collect(Collectors.toList());
        //男女比例
        var manCount = baseQuery.cloneQueryable().where(p -> p.eq(UserMemberDeptV::getSex, 0)).count();
        //男女年龄
        StringBuilder caseSql = new StringBuilder();
        caseSql.append(" case ");
        for (int i = 30; i < 51; i += 5) {
            caseSql.append(String.format(" WHEN u.age<%s THEN 'A%s' ", i, i));
        }
        caseSql.append(" else 'other' end ");

        var ageList0 = getArgsList(baseQuery.cloneQueryable().where(p->p.eq(UserMemberDeptV::getSex,0)), caseSql);
        var ageList1 = getArgsList(baseQuery.cloneQueryable().where(p->p.eq(UserMemberDeptV::getSex,1)), caseSql);

        //t1党员统计,t2汉族人数，t3学历，t4男性人数(总数在党员统计中)，t5年龄分别
        return (R)R.ok(Tuples.of(memberList,hanCount,edus,manCount,ageList0,ageList1));
    }

    private List<Object[]> getArgsList(Queryable<UserMemberDeptV> query, StringBuilder caseSql) {
        var sqlC= query.select(p -> p.sqlNativeSegment("TIMESTAMPDIFF(YEAR, birth, CURDATE()) age"))
                .toSQLResult();

        var sql=sqlC.getSQL();
        var params=sqlC.getSqlContext().getParameters().stream().map(p->p.getValue()).toArray();
        var ageList= queryHelper.CreateItems(String.format("SELECT ages `key`,count(1) `value` FROM(select %s ages from (%s) u) au group by ages", caseSql,sql),params)
                 .resultPkg().sqlQuery(DefaultKeyValue.class).stream().map(p->new Object[]{p.getValue(),p.getKey()}).collect(Collectors.toList());
        return ageList;
    }

    @ApiOperation(value = "站点统计信息",notes = "t1文章数，t2栏目数,t3{栏目:文章数}对象")
    @GetMapping(value = "webStat")
    public R<Tuple2<Long,Long>> webStat(Long deptId) {
        var typeCount = queryHelper.queryable(NewsType.class).where(deptId != null, p -> p.eq(IDeptEntity::getDeptId, deptId)).count();
        var newsCount = queryHelper.queryable(News.class).where(deptId != null, p -> p.eq(IDeptEntity::getDeptId, deptId)).count();
        var typeNewsCountList = queryHelper.queryable(NewsType.class)
                .leftJoin(News.class, (p1, p2) -> p1.eq(p2, NewsType::getId, News::getTypeId))
                .where(deptId != null, p -> p.eq(IDeptEntity::getDeptId, deptId))
                .groupBy((p, p1) -> p.column(NewsType::getId))
                .select(DefaultKeyValue.class, (p, p1) -> {
                    p.getColumnAsSelector().columnMaxAs(EasyLambdaUtil.getPropertyName(NewsType::getName), "key");
                    p1.getColumnAsSelector().columnCountAs(EasyLambdaUtil.getPropertyName(News::getId), "value");
                }).toList();
        var entryArr = typeNewsCountList.stream().map(DefaultKeyValue::toMapEntry).toArray(Map.Entry[]::new);
        var map = MapUtil.ofEntries(entryArr);
        return R.ok(Tuples.of(newsCount, typeCount, typeNewsCountList));
    }

     List<DeptOrgVo> filterChilds(Long deptId,List<DeptOrgVo> list) {
        var deptIdStr = deptId.toString();
        return list.stream().filter(p -> Objects.equals(p.getId(), deptId) || Objects.equals(p.getParentId(), deptId) || p.getAncestors().contains("," + deptIdStr + ",")).collect(Collectors.toList());
    }
    //组织
    @ApiOperation(value = "组织统计信息",notes = "t1组织数,t2党委数,t3总支数,t4支部数,t5党员数")
    @GetMapping(value = "OrgStat")
    public R  OrgStat(Long deptId) {
        var  deptStatN= orgService.deptInfoStat(new DeptOrgVo()).getData();
        var deptStat= orgService.deptVoList(null).getData();
        if(deptId!=null)
            deptStat=filterChilds(deptId, deptStat);
        DataUtil.findSet(deptStat,deptStatN
                ,(p,p1)-> Objects.equals(p.getDeptId(), p1.getDeptId())
                ,(p, p1)->{p.setStatMember(p1.getStatMember());p.setStatTeamPerson(p1.getStatTeamPerson());});

        var orgCount = deptStat.size();
        final var orgType1 = 0l;
        final var orgType2 = 1l;
        final var orgType3 = ListUtil.of(2l, 3, 4);

        var type1Count = deptStat.stream().filter(p ->Objects.equals(p.getType(),orgType1)).count();
        var type2Count = deptStat.stream().filter(p -> Objects.equals(p.getType(), orgType2)).count();
        var type3Count = deptStat.stream()
                .filter(p -> p.getType() != null && orgType3.contains(p.getType())).count();
        //
//        var memberCount = deptStat.stream()
//                .filter(p ->  (p.getParentId() == null || p.getParentId() == 0)&&p.getStatMember()!=null)
//                .mapToLong(DeptOrgVo::getStatMember).sum();
        //党员数量
        var memberCount = queryHelper.queryable(UserMemberDeptV.class)
                .where(p -> p.eq(UserMemberDeptV::getDelFlag, 0).isNotNull(UserMemberDeptV::getId))
                .where(deptId!=null,p->p.sqlNativeSegment("(dept_id={0} or FIND_IN_SET({0},{1}))", x -> x.value(deptId).expression(UserMemberDeptV::getDeptAncestors)))
                .count();
        return R.ok(Tuples.of(orgCount, type1Count, type2Count, type3Count, memberCount));
    }
    //积分
    @ApiOperation(value = "积分统计信息",notes = "t1党员排名,t2组织排名-statMember表示人员数量;deptId党员排名的部门范围")
    @GetMapping(value = "ScoreStat")
    public R<Tuple2<List<ScoreYearStatVo>, List<ScoreYearStatVo>>> ScoreStat(Integer year, Integer top,Long deptId) {
        year = year == null ? DateUtil.year(new Date()) : year;
        top = top == null ? 5 : top;
        //组织排名
        var where = new ScoreYearStatVo();
        where.setYearSign(year.longValue());
        var page = new PageSort();
        page.setPageSize(top);
        page.setOrderByName("scoreSum");
        page.setDescIs(true);
        var orgRank = scoreService.orgYearStat(where, page);
        DataUtil.toMapList(orgRank.getData(), null);
        var deptStat = orgService.deptInfoStat(new DeptOrgVo());
        var orgList = DataUtil.findSetRe(orgRank.getData(), deptStat.getData(),
                (p, p1) -> Objects.equals(p.getDeptId(), p1.getDeptId()),
                (p, p1) -> DataUtil.toMap(p, x -> x.put("statMember", p1.getStatMember()))
        );
        //个人排名
        where.setDeptId(deptId);
        var memberRank = scoreService.memberYearStat(where, page);
        //
        var map = new JSONObject();
        map.put("memberRank", memberRank.getData());
        map.put("orgRank", orgList);

        return (R) R.ok(Tuples.of(memberRank.getData(), orgList));
    }

    @ApiOperation(value = "评议统计信息",notes = "t1开展组织数，t2参与用户数")
    @GetMapping(value = "reviewStat")
    public R<Tuple2<Long,Long>> reviewStat(Long deptId) {

        List<Long> deptIds = getDeptIds(deptId);
        var deptCount = queryHelper.queryable(Review.class)
                .where(deptIds != null, p -> p.in(Review::getDeptId, deptIds))
                .select(p -> p.column(Review::getDeptId)).distinct().count();
        var userCount = queryHelper.queryable(ReviewStaffs.class)
                .where(deptIds != null, p -> p.in(ReviewStaffs::getDeptId, deptIds))
                .select(p -> p.column(ReviewStaffs::getUserId)).distinct().count();
        return R.ok(Tuples.of(deptCount, userCount));
    }

    private List<Long> getDeptIds(Long deptId) {
        List<Long> deptIds = deptId == null ? null : orgService.queryAndSubs(deptId).getData().stream().map(DeptOrgVo::getDeptId).collect(Collectors.toList());
        return deptIds;
    }

    @ApiOperation(value = "评议列表",notes = "")
    @GetMapping(value = "reviewList")
    public TableDataInfoRows<Review> reviewList(Review review, PageDomain pageRequest,Long deptId) {

        var deptIds=getDeptIds(deptId);
        var reList = queryHelper.queryable(Review.class)
                .where(deptIds!=null, p->p.in(IDeptEntity::getDeptId,deptIds))
                .whereObject(review).orderByDesc(p->p.column(Review::getId)).toPageResult(pageRequest.getPageNum(),pageRequest.getPageSize());
        //
        var orgList = orgService.deptVoList(null).getData();
        var reMaps = DataUtil.findSetRe(reList.getData(), orgList, (p, p1) -> Objects.equals(p.getDeptId(), p1.getDeptId()), (p, p2) -> {
            Map map = DataUtil.toMap(p, null);
            map.put("deptName", p2.getDeptName());
            return map;
        });
        var re = new TableDataInfoRows(reList.getTotal(), reMaps);
        return re;
    }

    //会议
    @ApiOperation(value = "会议统计",notes = "t1党支部党员大会(0),t2支部委员会(1),t3党小组会(2),t4党课(3)")
    @GetMapping(value = "meetingStat")
    public R<Tuple4<Long,Long,Long,Long>> meetingStat(Long deptId) {
        var mtype0= DictPB.meeting_type.党支部党员大会.getValue();
        var mtype1=DictPB.meeting_type.支部委员会.getValue();
        var mtype2=DictPB.meeting_type.党小组会.getValue();
        var mtype3=DictPB.meeting_type.党课.getValue();
        var baseQuery= queryHelper.queryable(MeetingInfo.class).where(p->p.in(MeetingInfo::getStatus,new Long[]{1l,2l}));
        var deptIds=getDeptIds(deptId);
        baseQuery.where(deptIds!=null, p->p.in(IDeptEntity::getDeptId,deptIds));
        var mtype0Count=baseQuery.cloneQueryable().where(p->p.eq(MeetingInfo::getTypeCode,mtype0)).count();
        var mtype1Count=baseQuery.cloneQueryable().where(p->p.eq(MeetingInfo::getTypeCode,mtype1)).count();
        var mtype2Count=baseQuery.cloneQueryable().where(p->p.eq(MeetingInfo::getTypeCode,mtype2)).count();
        var mtype3Count=baseQuery.cloneQueryable().where(p->p.eq(MeetingInfo::getTypeCode,mtype3)).count();

        return R.ok(Tuples.of(mtype0Count,mtype1Count,mtype2Count,mtype3Count));
    }

    @Resource
    TeamRecordServiceImpl teamRecordService;
    @ApiOperation(value = "部门相关信息汇总",notes = "t1部门信息,t2部门班子成员信息")
    @GetMapping(value = "deptInfo")
    public R<Tuple2<DeptOrgVo, List<Map>>> deptInfo(Long deptId){
        var deptVoList=orgService.deptInfoStat(new DeptOrgVo(){{setDeptId(deptId);}});


        if (deptVoList.getData() == null || deptVoList.getData().isEmpty()) return  R.bad("无法找到指定部门");
        DeptOrgVo deptVo = deptVoList.getData().get(0);
        var teamList=teamRecordService.nowEffectiveTeam(deptId);
        List<Map> teamPersonsMaps=new ArrayList<>();
        if(teamList.isSuccess()&& !teamList.getData().isEmpty()) {
            var nowTeam = queryHelper.query().queryable(TeamRecord.class).include(p -> p.many(TeamRecord::getTeamPersons))
                    .whereObject(teamList.getData().get(0)).orderByDesc(p -> p.column(TeamRecord::getYear)).firstOrNull();
            var pers = nowTeam.getTeamPersons();
            teamPersonsMaps = DataUtil.toMapList(pers,null);
            /**  追加用户头像
            var ids = pers.stream().map(TeamPerson::getUserId).collect(Collectors.toList());
            var userList = queryHelper.queryable(SysUserRef.class).whereByIds(ids).toList();
            teamPersonsMaps = DataUtil.toMapList(pers, p -> {
                var user = userList.stream().filter(x -> x.getUserId() == p.get("userId")).findFirst();
                user.ifPresent(sysUserRef -> p.put("avatar", sysUserRef.getAvatar()));
            });
             */
        }
        return R.ok(Tuples.of(deptVo,teamPersonsMaps));
    }
}
